/**
 * @author Vitor Franco do Carmo (vitor.carmo@capgemini.com)
 * @since 08/04/2013
 *
 */
package br.com.vfcfw.controller.listener;

import java.io.IOException;

import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.log4j.Logger;

import br.com.vfcfw.commons.util.ConstantesArquitetura;
import br.com.vfcfw.commons.util.LogUtil;
import br.com.vfcfw.commons.util.MensagemUtil;
import br.com.vfcfw.commons.util.ValidacaoUtil;

/**
 * Implementação do {@link PhaseListener} responsável pela segurança da aplicação.
 * 
 * @author Vitor Franco do Carmo (vitor.carmo@capgemini.com)
 * @since 08/04/2013
 * 
 */
public class SecurityPhaseListener implements PhaseListener {

    /** */
    private static final long serialVersionUID = -2960135838097681971L;

    private Logger logger = Logger.getLogger(SecurityPhaseListener.class);

    /**
     * Construtor da classe.
     */
    public SecurityPhaseListener() {

        super();
    }

    /**
     * {@inheritDoc}
     * 
     * @see javax.faces.event.PhaseListener#afterPhase(javax.faces.event.PhaseEvent)
     */
    @Override
    public void afterPhase(PhaseEvent event) {

        ;
    }

    /**
     * {@inheritDoc}
     * 
     * @see javax.faces.event.PhaseListener#beforePhase(javax.faces.event.PhaseEvent)
     */
    @Override
    public void beforePhase(PhaseEvent event) {

        FacesContext fc = event.getFacesContext();

        String loginPage = (String) fc.getExternalContext().getRequestMap()
            .get("web.secfilter.authenticator.showLogin");

        if (ValidacaoUtil.possuiValor(loginPage)) {
            doRedirect(fc, loginPage);
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see javax.faces.event.PhaseListener#getPhaseId()
     */
    @Override
    public PhaseId getPhaseId() {

        return PhaseId.RESTORE_VIEW;
    }

    /**
     * Redireciona a aplicação para uma determinada página.
     * 
     * @param facesContext {@link FacesContext}.
     * @param redirectPage Página para a qual será redirecionada.
     */
    public void doRedirect(FacesContext facesContext, String redirectPage) {

        ExternalContext ec = facesContext.getExternalContext();

        try {
            if (ec.isResponseCommitted()) {

                // redirect não é possível nessa situação
                return;
            }

            // fix para renderer kit (Mojarra's e PrimeFaces's ajax redirect)
            if ((facesContext.getPartialViewContext().isPartialRequest())
                && facesContext.getResponseWriter() == null
                && facesContext.getRenderKit() == null) {
                ServletResponse response = (ServletResponse) ec.getResponse();
                ServletRequest request = (ServletRequest) ec.getRequest();
                response.setCharacterEncoding(request.getCharacterEncoding());

                RenderKitFactory factory = (RenderKitFactory) FactoryFinder
                    .getFactory(FactoryFinder.RENDER_KIT_FACTORY);

                RenderKit renderKit = factory.getRenderKit(facesContext, facesContext.getApplication().getViewHandler()
                    .calculateRenderKitId(facesContext));

                ResponseWriter responseWriter = renderKit.createResponseWriter(response.getWriter(), null,
                    request.getCharacterEncoding());
                facesContext.setResponseWriter(responseWriter);
            }

            ec.redirect(ec.getRequestContextPath() + (redirectPage != null ? redirectPage : ""));

        } catch (IOException e) {

            LogUtil.error(logger,
                MensagemUtil.obterMensagem(ConstantesArquitetura.MSG_ERRO_REDIRECIONAR_PAGINA, redirectPage));
            throw new FacesException(e);
        }
    }

}
